package com.elitedatai.mchtest.mission.service.impl;


import com.dji.sdk.cloudapi.wayline.OutOfControlActionEnum;
import com.dji.sdk.cloudapi.wayline.TaskTypeEnum;
import com.dji.sdk.cloudapi.wayline.WaylineTypeEnum;
import com.dji.sdk.common.HttpResultResponse;
import com.elitedatai.mchtest.common.model.CustomClaim;
import com.elitedatai.mchtest.mission.entity.FlightPlan;
import com.elitedatai.mchtest.mission.enums.PlanStatus;
import com.elitedatai.mchtest.mission.model.dto.FlightPlanDTO;
import com.elitedatai.mchtest.mission.repository.FlightPlanRepository;
import com.elitedatai.mchtest.mission.service.IFlightPlanService;
import com.elitedatai.mchtest.wayline.model.enums.WaylineJobStatusEnum;
import com.elitedatai.mchtest.wayline.model.param.CreateJobParam;
import com.elitedatai.mchtest.wayline.service.IFlightTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.Optional;

@Service
@Slf4j
public class FlightPlanServiceImpl implements IFlightPlanService {

    @Autowired
    private FlightPlanRepository flightPlanRepository;

    @Autowired
    private IFlightTaskService flightTaskService;

    @Override
    public CreateJobParam createFlightPlan(FlightPlanDTO flightPlanDTO) {
        flightPlanDTO.setStatus(PlanStatus.PENDING.getVal());

        // 转换DTO为实体
        FlightPlan flightPlan = dtoToEntity(flightPlanDTO);

        // 保存到数据库
        flightPlanRepository.save(flightPlan);
        
        // 转换为CreateJobParam
        return flightPlanToCreateJobParam(flightPlan);
    }

    @Override
    public HttpResultResponse publishFlightTask(CreateJobParam param, CustomClaim customClaim) {
        HttpResultResponse response = null;
        // 调用任务服务发布任务
        try{
            response = flightTaskService.publishFlightTask(param, customClaim);
        }catch (SQLException e){
            log.error("发布飞行任务失败", e);
            response = HttpResultResponse.error("发布飞行任务失败");
        }
        return response;
    }

    @Override
    public FlightPlan save(FlightPlan flightPlan) {
        return flightPlanRepository.save(flightPlan);
    }

    /**
     * FlightPlan转CreateJobParam
     * @param flightPlan 飞行计划实体
     * @return 创建任务参数
     */
    private CreateJobParam flightPlanToCreateJobParam(FlightPlan flightPlan) {
        if (flightPlan == null) {
            return null;
        }

        CreateJobParam param = new CreateJobParam();
        param.setMissionId(flightPlan.getMissionId());
        param.setName(flightPlan.getName());
        param.setFileId(flightPlan.getWaylineId()); // 使用waylineId作为fileId
        param.setDockSn(flightPlan.getDockSn());
        
        // 枚举类型转换
        if (flightPlan.getWaylineType() != null) {
            param.setWaylineType(WaylineTypeEnum.find(flightPlan.getWaylineType()));
        }
        
        if (flightPlan.getTaskType() != null) {
            param.setTaskType(TaskTypeEnum.find(flightPlan.getTaskType()));
        }
        
        if (flightPlan.getOutOfControlAction() != null) {
            param.setOutOfControlAction(OutOfControlActionEnum.find(flightPlan.getOutOfControlAction()));
        }
        
        param.setRthAltitude(flightPlan.getRthAltitude());
        param.setMinBatteryCapacity(flightPlan.getMinBatteryCapacity());
        param.setMinStorageCapacity(flightPlan.getMinStorageCapacity());
        param.setTaskDays(flightPlan.getTaskDays());
        param.setPlanId(flightPlan.getPlanId());
        param.setTaskPeriods(flightPlan.getTaskPeriods());

        return param;
    }

    /**
     * DTO转实体
     * @param dto 飞行计划DTO
     * @return 飞行计划实体
     */
    private FlightPlan dtoToEntity(FlightPlanDTO dto) {
        if (dto == null) {
            return null;
        }

        FlightPlan entity = new FlightPlan();
        entity.setId(dto.getId());
        entity.setName(dto.getName());
        entity.setMissionId(dto.getMissionId());
        entity.setFlyerId(dto.getFlyerId());
        entity.setWaylineId(dto.getWaylineId());
        entity.setDockSn(dto.getDockSn());
        entity.setWaylineType(dto.getWaylineType());
        entity.setTaskType(dto.getTaskType());
        entity.setRthAltitude(dto.getRthAltitude());
        entity.setOutOfControlAction(dto.getOutOfControlAction());
        entity.setMinBatteryCapacity(dto.getMinBatteryCapacity());
        entity.setMinStorageCapacity(dto.getMinStorageCapacity());
        entity.setTaskDays(dto.getTaskDays());
        entity.setTaskPeriods(dto.getTaskPeriods());
        entity.setStatus(dto.getStatus());
        entity.setJobId(dto.getJobId());

        return entity;
    }

    @Override
    public Page<FlightPlanDTO> getAllFlightPlans(Pageable pageable) {
        Page<FlightPlan> flightPlanPage = flightPlanRepository.findAllOrderByCreateTimeDesc(pageable);
        return flightPlanPage.map(this::entityToDto);
    }

    @Override
    public Page<FlightPlanDTO> getFlightPlansByStatus(Integer status, Pageable pageable) {
        Page<FlightPlan> flightPlanPage = flightPlanRepository.findByStatusOrderByCreateTimeDesc(status, pageable);
        return flightPlanPage.map(this::entityToDto);
    }

    @Override
    public Page<FlightPlanDTO> getFlightPlansByDockSn(String dockSn, Pageable pageable) {
        Page<FlightPlan> flightPlanPage = flightPlanRepository.findByDockSnOrderByCreateTimeDesc(dockSn, pageable);
        return flightPlanPage.map(this::entityToDto);
    }

    @Override
    public Page<FlightPlanDTO> getFlightPlansByFlyerId(String flyerId, Pageable pageable) {
        Page<FlightPlan> flightPlanPage = flightPlanRepository.findByFlyerIdOrderByCreateTimeDesc(flyerId, pageable);
        return flightPlanPage.map(this::entityToDto);
    }

    @Override
    public FlightPlan getFlightPlanByPlanId(String planId) {
        Optional<FlightPlan> flightPlanOptional = flightPlanRepository.findByPlanId(planId);
        return flightPlanOptional.orElse(null);
    }
    
    @Override
    @Transactional
    public void updateStatusByJobId(String jobId, Integer jobStatus) {
        if (jobId == null || jobStatus == null) {
            log.warn("更新飞行计划状态失败：jobId或jobStatus为空");
            return;
        }
        Integer status = jobStatus;
        WaylineJobStatusEnum waylineJobStatusEnum = WaylineJobStatusEnum.find(jobStatus);
        if(waylineJobStatusEnum.getEnd()==true){
            status = PlanStatus.COMPLETED.getVal();
        }else{
            status = PlanStatus.EXECUTING.getVal();
        }
        int updatedRows = flightPlanRepository.updateStatusByJobId(jobId, status);
        if (updatedRows > 0) {
            log.info("成功更新飞行计划状态：jobId={}, status={}, 更新记录数={}", jobId, status, updatedRows);
        } else {
            log.warn("未找到对应的飞行计划记录：jobId={}", jobId);
        }
    }

    /**
     * 实体转DTO
     * @param entity 飞行计划实体
     * @return 飞行计划DTO
     */
    private FlightPlanDTO entityToDto(FlightPlan entity) {
        if (entity == null) {
            return null;
        }

        FlightPlanDTO dto = new FlightPlanDTO();
        dto.setId(entity.getId());
        dto.setName(entity.getName());
        dto.setMissionId(entity.getMissionId());
        dto.setFlyerId(entity.getFlyerId());
        dto.setWaylineId(entity.getWaylineId());
        dto.setDockSn(entity.getDockSn());
        dto.setWaylineType(entity.getWaylineType());
        dto.setTaskType(entity.getTaskType());
        dto.setRthAltitude(entity.getRthAltitude());
        dto.setOutOfControlAction(entity.getOutOfControlAction());
        dto.setMinBatteryCapacity(entity.getMinBatteryCapacity());
        dto.setMinStorageCapacity(entity.getMinStorageCapacity());
        dto.setTaskDays(entity.getTaskDays());
        dto.setTaskPeriods(entity.getTaskPeriods());
        dto.setStatus(entity.getStatus());
        dto.setJobId(entity.getJobId());
        dto.setCreateTime(entity.getCreateTime());
        dto.setUpdateTime(entity.getUpdateTime());

        return dto;
    }

}
